home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / L-M / mini / miniterm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-09-29  |  17.7 KB  |  629 lines  |  [TEXT/MPS ]

  1. /* A Simple MPW C Terminal Emulator
  2.  *
  3.  * New File: May 20,1986
  4.  * Jerry LeVan
  5.  * 325 Boone Trail Richmond Ky 40475
  6.  */
  7.  
  8. # include <types.h>                 /* Nearly always required */
  9. # include <quickdraw.h>             /* To access the qd globals */
  10. # include <fonts.h>                 /* Only for InitFonts() trap */
  11. # include <windows.h>
  12. # include <events.h>
  13. # include <menus.h>
  14. # include <segload.h>                /* UnloadSeg() */
  15. # include <textedit.h>                /* TEInit */
  16. # include <dialogs.h>                /* InitDialogs */
  17. # include <desk.h>                    /* Open desk accessory */
  18. # include <toolutils.h>
  19. # include <serial.h>
  20. # include <errors.h>
  21. # include <OSUtils.h>
  22.  
  23. Rect dragRect;           /* limit rect for dragging rectangles on the screen */
  24. Rect growRect;             /* limit rect for growing rectangles                */
  25.  
  26. WindowPtr myWindow;        /* the application window */
  27.  
  28. MenuHandle DeskMenu;
  29. MenuHandle FileMenu;
  30. MenuHandle EditMenu;
  31. MenuHandle OptionMenu;
  32. MenuHandle BaudMenu;
  33. MenuHandle ParityMenu;
  34. MenuHandle DataSizeMenu;
  35. MenuHandle PhoneMenu;
  36. MenuHandle FlowMenu;
  37. MenuHandle BSMenu;
  38. MenuHandle LocalMenu;
  39. MenuHandle CreatorMenu;
  40. MenuHandle XPrefsMenu;
  41. MenuHandle PortMenu;
  42.  
  43. #define Desk_ID   128    /* Id for the apple menu */
  44. #define File_ID   129    /* Id for the file  menu */
  45. #define Edit_ID   130    /* Id for the standard edit menu */
  46. #define Option_ID 131    /* Id for option list */
  47. #define Baud_ID      132    /* id for heirarchieal? menu */
  48. #define Parity_ID 133    /* id for parity menu */
  49. #define DataSize_ID 134 /* id for data size menu */
  50. #define Phone_ID    135 /* id for phone menu */
  51. #define Flow_ID        136 /* id for phone control menu */
  52. #define BS_ID        137 /* id for <bs> processing */
  53. #define Local_ID    138 /* id for full/half duplex flag */
  54. #define Creator_ID    139 /* id for text file creator menu */
  55. #define XPrefs_ID    140    /* id for xmodem preferences */
  56. #define Port_ID        141 /* id for port selection menu */
  57.  
  58. #define windowID    128  /* id for application window */
  59. #define aboutID        128     /* id for about dialog       */
  60.  
  61. #define AIn  -6
  62. #define AOut -7
  63. #define BIn  -8
  64. #define BOut -9
  65.  
  66. #define aboutItem    1     /* Item number for the about dialog */
  67.  
  68. extern _DataInit();         /* The Rumtime Initialization routine */
  69.  
  70. #define POPUP 0x0B             /* trap number for popupmenuselect */
  71. #define UNIMPLEMENTED 0x9F    /* "unimplemented" trap number */
  72.  
  73. #define CR 0x0d
  74.  
  75. /* this is defined in version two of MPW C */
  76. pascal long PopUpMenuSelect(menuh,top,left,item)
  77.   MenuHandle menuh;
  78.   short top;
  79.   short left;
  80.   short item;
  81.   extern 0xa80b;
  82.  
  83. Boolean moreToDo = true; /* set to false to exit program */
  84.  
  85. /* Globals for this application */
  86.  
  87. /*standard modem configuration */
  88. short config = baud1200 + stop10 + noParity + data8;
  89. short ourPort = sPortA;        /* Standard modem port for now */
  90. short sIn = AIn;
  91. short sOut = AOut;
  92. short baud = baud1200;        /* 1200 baud */
  93. short stopBits = stop10;    /* one stop bit */
  94. short parity = noParity;    /* no parity */
  95. short data = data8;            /* eight data bits */
  96.  
  97. short localEcho = 0;        /* full duplex */
  98. short BSflag = 0;            /* send BS as Delete */
  99. char XonXoff = 1;            /* flow control enabled */
  100. char doCrLf = 0;            /* true => echo cr as crlf */
  101. Boolean interpret_control = true; /* false means display on screen */
  102.  
  103. /* defined in File.c (for text file up/down load) */
  104. extern Boolean OkToSend();
  105. extern Boolean OkToReceive();
  106.  
  107.  
  108. /* the following five items track the users xmodem preferences */
  109. /* and are defined in the file xmodem.c */
  110.  extern char MacBinary ;    /* true means try macbinary else standard xmodem */
  111.  extern char TextXMode ;    /* true means append Lf after Cr on upload */
  112.                              /* and strip Lf after Cr on download */
  113.                         
  114.  extern char fastDL;        /* true implies a fast ack */
  115.  extern char forceCheckSum;    /* true means disable CRC */
  116.  
  117.  extern long sectorSize;    /* size of tranfer buffer */
  118.  
  119. /******************************************************************/
  120. long creator = 'MPS ';        /* default Text file creator signature */
  121.  
  122. Boolean asciiReceive = false; /* true means we are receiving a text file */
  123. short recRef;                /* reference number for received text file */
  124.  
  125. Boolean asciiSend = false;    /* true means we are sending a text file */
  126. short sendRef;                /* reference number for file we are sending */
  127.  
  128. short vRef;                    /* volume reference number for flush */
  129.  
  130. /* the following variable is defined in clock.c */
  131. extern Boolean showClock ;    /* if true show time in menu bar */
  132.  
  133. /**********************************************************************/
  134.  
  135. /* the following three variables control line pacing on text uploads */
  136. Boolean doPacing = false;    /* true means line pacing on upload */
  137. char paceCh = ':';            /* if pacing wait for this character */
  138. long delayAmt = 0;            /* delay time between characters(ticks) */
  139. Boolean foundPaceChar;        /* true means we are in a paced line upload */
  140. /* the following routine is defined in Vt100.c */
  141. extern Boolean OKToSendChar(); /* test to see if ok to send char */
  142.  
  143. /**********************************************************************/
  144. void SetLimitRects()
  145.   { SetRect(&dragRect,qd.screenBits.bounds.left+4,
  146.                       qd.screenBits.bounds.top+24,
  147.                       qd.screenBits.bounds.right-4,
  148.                       qd.screenBits.bounds.bottom-4);
  149.  
  150.     SetRect(&growRect,qd.screenBits.bounds.left,
  151.                         qd.screenBits.bounds.top+24,
  152.                         qd.screenBits.bounds.right,
  153.                         qd.screenBits.bounds.bottom);
  154.    }
  155. /**********************************************************************/
  156. void DoAboutDialog()
  157.  {     GrafPtr     savePort;
  158.     DialogPtr    theDialog;
  159.     short        itemType;
  160.     Handle        itemHdl;
  161.     Rect        itemRect;
  162.     short        itemHit;
  163.     EventRecord event;
  164.  
  165.     GetPort(&savePort);
  166.     HideWindow(myWindow);
  167.  
  168.      theDialog = GetNewDialog(aboutID ,0,(WindowPtr)-1); /* create the dialogue */
  169.      SetPort(theDialog);
  170.      
  171.      DrawDialog(theDialog);
  172.      
  173.      while(!GetNextEvent(mDownMask+keyDownMask+autoKeyMask,&event)) ;
  174.      DisposDialog(theDialog);
  175.  
  176.     ShowWindow(myWindow);
  177.     SetPort(savePort);
  178.     
  179. }
  180.  
  181.  
  182. /**********************************************************************/
  183. void DoUpDate()
  184.  { /* refresh the window */
  185.    term_redraw();
  186.   }
  187. /**********************************************************************/
  188.  void DoMenu(menuresult)
  189.     long menuresult;
  190.     { 
  191.     short menuID, itemNumber,i;
  192.     char AccessoryName[80];
  193.     
  194.     menuID = HiWord(menuresult);
  195.     itemNumber = menuresult;
  196.     stop_cursor();
  197.     switch ( menuID )
  198.      {
  199.       case File_ID:
  200.           switch(itemNumber){
  201.             case 1: if(asciiReceive){
  202.                         FSClose(recRef); recRef = 0;
  203.                         asciiReceive = false;
  204.                         SetItem(FileMenu,itemNumber,"Start Text Capture...");
  205.                         FlushVol(vRef);
  206.                         }
  207.                     else
  208.                      if (OkToReceiveFile(&recRef,&vRef,creator)){
  209.                          SetItem(FileMenu,itemNumber,"Stop Text Capture");
  210.                         asciiReceive = true;
  211.                        }
  212.                      break;
  213.             case 2: if(asciiSend){
  214.                          FSClose(sendRef);sendRef = 0;
  215.                         asciiSend = false;
  216.                         SetItem(FileMenu,itemNumber,"Start Text Upload...");
  217.                         }
  218.                     else
  219.                     if(OkToSendFile(&sendRef)){
  220.                         SetItem(FileMenu,itemNumber,"Stop Text Upload");
  221.                         asciiSend = true;
  222.                         foundPaceChar = false;}
  223.                     break;
  224.             case 4: HideWindow(myWindow);
  225.                     DoPaceDialog(&paceCh,&doPacing,&delayAmt);
  226.                     UnloadSeg(DoPaceDialog);
  227.                     ShowWindow(myWindow);
  228.                     break;
  229.             case 6: FlowControl(sOut,0); /* turn flow control off */
  230.                     Xreceive(); UnloadSeg(Xreceive);
  231.                     if(XonXoff)FlowControl(sOut,1); /* reset if necessary */
  232.                     break;    /* xmodem receive file */
  233.             case 7: FlowControl(sOut,0); /* turn off flow control */
  234.                     Xsend(); UnloadSeg(Xsend);
  235.                     if(XonXoff)FlowControl(sOut,1);
  236.                     break;        /* xmodem send a file */
  237.             case 10: LaunchAppl(ourPort,asciiReceive,recRef,asciiSend,sendRef);
  238.                     UnloadSeg(LaunchAppl);
  239.                     break;            
  240.             case 12: /* shutdown stuff */
  241.                     RAMSDClose(ourPort);
  242.                     if(showClock)stopClock(); /* remove timer queue element */
  243.                     moreToDo = false;
  244.                     break;
  245.               default: break;    
  246.             }
  247.              break;
  248.       case Desk_ID:
  249.         if(itemNumber == aboutItem) { DoAboutDialog(); break;}
  250.         GetItem(DeskMenu, itemNumber, AccessoryName);
  251.         OpenDeskAcc(AccessoryName);
  252.         break;
  253.       case Edit_ID:
  254.         SystemEdit(itemNumber-1);
  255.         break;
  256.       case Baud_ID:
  257.         for(i=1;i<=7;i++)CheckItem(BaudMenu,i,0);
  258.         switch (itemNumber)
  259.          { case 1: baud = baud300; break;
  260.            case 2: baud = baud1200;  break;
  261.            case 3: baud = baud2400;  break;
  262.            case 4: baud = baud4800;  break;
  263.            case 5: baud = baud9600;  break;
  264.            case 6: baud = baud19200;  break;
  265.            case 7: baud = baud57600;  break;
  266.           }
  267.          CheckItem(BaudMenu,itemNumber,1);
  268.          SerReset(sOut,baud + stopBits + data + parity);
  269.          SerReset(sIn, baud + stopBits + data + parity);
  270.          break;
  271.       case Local_ID:
  272.          switch(itemNumber){
  273.            case 1: localEcho = 1 ;
  274.                        CheckItem(LocalMenu,1,1);
  275.                     CheckItem(LocalMenu,2,0);
  276.                     break;
  277.             case 2: localEcho = 0 ;
  278.                     CheckItem(LocalMenu,1,0);
  279.                     CheckItem(LocalMenu,2,1);
  280.                     break;
  281.             default: break;
  282.             }
  283.           break;
  284.       case BS_ID:
  285.          switch(itemNumber){
  286.            case 1: BSflag = 0 ;
  287.                        CheckItem(BSMenu,1,1);
  288.                     CheckItem(BSMenu,2,0);
  289.                     break;
  290.             case 2: BSflag = 1 ;
  291.                     CheckItem(BSMenu,1,0);
  292.                     CheckItem(BSMenu,2,1);
  293.                     break;
  294.             default: break;
  295.             }
  296.           break;
  297.       case Flow_ID:
  298.          switch(itemNumber){
  299.            case 1: XonXoff = 1 ;
  300.                        CheckItem(FlowMenu,1,1);
  301.                     CheckItem(FlowMenu,2,0);
  302.                     break;
  303.             case 2: XonXoff = 0 ;
  304.                     CheckItem(FlowMenu,1,0);
  305.                     CheckItem(FlowMenu,2,1);
  306.                     break;
  307.             default: break;
  308.             }
  309.             FlowControl(sOut,XonXoff);
  310.             break;
  311.       case Option_ID:
  312.          switch(itemNumber){
  313.            case 9:  showClock = !showClock;
  314.                        CheckItem(OptionMenu,9,showClock);
  315.                     if(showClock)startClock();
  316.                     else stopClock();
  317.                     break;
  318.            case 10: Control(sOut,22,nil); break;
  319.            case 11: doCrLf = !doCrLf;
  320.                        CheckItem(OptionMenu,11,doCrLf);
  321.                     break;
  322.            case 12: ShowReadStats(); break;
  323.            case 14: interpret_control = !interpret_control;
  324.                        CheckItem(OptionMenu,14,interpret_control);
  325.                     break;
  326.            case 15:    reset_term();
  327.                        break;
  328.            case 16:    
  329.                        HideWindow(myWindow);
  330.                        SelectCursorStyle();
  331.                     UnloadSeg(SelectCursorStyle);
  332.                     ShowWindow(myWindow);
  333.                     break;
  334.            default: break;
  335.           }
  336.          break;
  337.       case Phone_ID:
  338.             HideWindow(myWindow);
  339.           PhoneManager(sOut);UnloadSeg(PhoneManager);
  340.           ShowWindow(myWindow);
  341.           break;
  342.       case Creator_ID:  /* order must match menu */
  343.             for(i=1; i<=4 ; i++) CheckItem(CreatorMenu,i,0);
  344.           switch(itemNumber){
  345.            case 1: creator = 'EDIT'; break;
  346.            case 2: creator = 'MACA'; break;
  347.            case 3: creator = 'MSWD'; break;
  348.            case 4: creator = 'MPS '; break;
  349.            default: break;
  350.            }
  351.            CheckItem(CreatorMenu,itemNumber,1);
  352.            break;
  353.       case XPrefs_ID:
  354.              switch(itemNumber){
  355.            case 1: /* MacBinary */
  356.                      CheckItem(XPrefsMenu,1,1);
  357.                   CheckItem(XPrefsMenu,2,0);
  358.                   CheckItem(XPrefsMenu,3,0);
  359.                   MacBinary = 1;
  360.                   TextXMode = 0;
  361.                   break;
  362.            case 2: /* Text */
  363.                      CheckItem(XPrefsMenu,1,0);
  364.                   CheckItem(XPrefsMenu,2,1);
  365.                   CheckItem(XPrefsMenu,3,0);
  366.                   MacBinary =0;
  367.                   TextXMode =1;
  368.                   break;
  369.            case 3: /* straight */
  370.                      CheckItem(XPrefsMenu,1,0);
  371.                   CheckItem(XPrefsMenu,2,0);
  372.                   CheckItem(XPrefsMenu,3,1);
  373.                   MacBinary = 0;
  374.                   TextXMode = 0;
  375.                   break;
  376.            case 5: forceCheckSum = !forceCheckSum;
  377.                       CheckItem(XPrefsMenu,5,forceCheckSum);
  378.                    break;
  379.            case 6: if(sectorSize == 128){
  380.                         sectorSize = 1024;
  381.                      SetItem(XPrefsMenu,6,"1024 Byte Buffer");}
  382.                    else{
  383.                      sectorSize = 128;
  384.                      SetItem(XPrefsMenu,6,"128 Byte Buffer");}
  385.                    CheckItem(XPrefsMenu,6,1);
  386.                    break;
  387.            case 7: fastDL = !fastDL;
  388.                        CheckItem(XPrefsMenu,7,fastDL);
  389.                     break;
  390.            default: break;
  391.             }
  392.             break;
  393.       default: break;
  394.      } /* switch menuID */
  395.     start_cursor();      
  396.     HiliteMenu(0);
  397.     }
  398. /**********************************************************************/
  399. # define __SEG__ Initialize
  400.  
  401. Boolean InitProgram()
  402. {   /* Standard Initialization Sequence */
  403.  
  404.      long menuresult;
  405.      short itemNumber,menuID;
  406.  
  407.     /* Standard Manager Initialization Sequence */
  408.     MoreMasters(); MoreMasters();
  409.     InitGraf(&qd.thePort);    /* set up quickdraw */
  410.     InitFonts();            /* Set up fonts        */
  411.     FlushEvents(everyEvent,0);    /* empty the event queue */
  412.     InitWindows();            /* Set up window manager */
  413.     InitMenus();            /* Set up menus */
  414.     TEInit();                /* Needed for Dialogs */
  415.     InitDialogs(nil);        /* No restart proc */
  416.     
  417.     /* check to make sure we have popupmenus etc */
  418.     if(NGetTrapAddress(POPUP,ToolTrap) == 
  419.        NGetTrapAddress(UNIMPLEMENTED,ToolTrap)) {
  420.          ErrorMessage("System 4.1 or later is required",0);
  421.          return false;
  422.     }
  423.  
  424.     /* Now the program stuff */
  425.     
  426.     /* Desk Accessory menu */
  427.       DeskMenu = GetMenu(Desk_ID);
  428.       AddResMenu(DeskMenu, 'DRVR');
  429.       InsertMenu(DeskMenu, 0);
  430.       
  431.      /* "File" menu */
  432.       FileMenu = GetMenu(File_ID);
  433.       InsertMenu(FileMenu,0);
  434.      
  435.      /* "Edit" menu */
  436.       EditMenu = GetMenu(Edit_ID);
  437.       InsertMenu(EditMenu,0);
  438.       
  439.      /* "Baud" Menu */
  440.       BaudMenu = GetMenu(Baud_ID);
  441.       InsertMenu(BaudMenu,-1);    /* Heirarchial menu insert */
  442.       
  443.      /* "Parity" Menu */
  444.       ParityMenu = GetMenu(Parity_ID);
  445.       InsertMenu(ParityMenu,-1);
  446.       
  447.      /* "DataSize" Menu */
  448.       DataSizeMenu = GetMenu(DataSize_ID);
  449.       InsertMenu(DataSizeMenu,-1);
  450.       
  451.      /* "Option" Menu */
  452.       OptionMenu = GetMenu(Option_ID);
  453.       InsertMenu(OptionMenu,0);
  454.       
  455.      /* Phone Menu */
  456.       PhoneMenu = GetMenu(Phone_ID);
  457.       InsertMenu(PhoneMenu, 0);
  458.       
  459.      /* flow control menu */
  460.      FlowMenu = GetMenu(Flow_ID);
  461.      InsertMenu(FlowMenu,-1);
  462.      
  463.      /* BS menu */
  464.      BSMenu = GetMenu(BS_ID);
  465.      InsertMenu(BSMenu,-1);
  466.      
  467.      /* Local echo menu */
  468.       LocalMenu = GetMenu(Local_ID);
  469.       InsertMenu(LocalMenu,-1);
  470.       
  471.      /* Text file creator menu */
  472.       CreatorMenu = GetMenu(Creator_ID);
  473.       InsertMenu(CreatorMenu,-1);
  474.       
  475.      /* Xmodem preferences menu */
  476.       XPrefsMenu = GetMenu(XPrefs_ID);
  477.       InsertMenu(XPrefsMenu,-1);
  478.       
  479.      /* Port Selection menu */
  480.       PortMenu = GetMenu(Port_ID);
  481.       InsertMenu(PortMenu,-1);
  482.       
  483.      DrawMenuBar();
  484.      
  485.      /* create the application window */     
  486.      myWindow = GetNewWindow(windowID, 0, (WindowPtr) -1);
  487.      SetPort(myWindow);
  488.      SetLimitRects();
  489.      
  490.      /* if mouse is down select port */
  491.      menuresult=PopUpMenuSelect(PortMenu,100,200,1);
  492.      menuID = HiWord(menuresult);
  493.      itemNumber = menuresult;
  494.      if(menuID == Port_ID)
  495.        switch(itemNumber){
  496.          case 1: ourPort = sPortA;
  497.                  sIn = AIn;
  498.                  sOut = AOut;
  499.                  break;
  500.          case 2: ourPort = sPortB;
  501.                  sIn = BIn;
  502.                  sOut = BOut;
  503.                  break;
  504.          default: break;
  505.         }
  506.      InitModem(ourPort,config); /* set up the modem */
  507.      InitPage();                /* set up screen handler */
  508.      setup_crc_tables();        /* set up crc table */
  509.      InitClock();                /* turn on the clock */
  510.      InitCursor();                /* last initialization */
  511.      return true;
  512.  }     
  513.  
  514.  
  515. /**********************************************************************/
  516. # define __SEG__ Main
  517. MainEventLoop()
  518. {    GrafPtr tmpWindow;
  519.     WindowPtr whichwindow;
  520.     EventRecord event;
  521.     long sel,cnt,tmp;
  522.     unsigned char ch,code;
  523.     short err;
  524.     
  525.     SystemTask(); /* allow desk accessories time */
  526.     
  527.     /* Check if we are uploading a file */
  528.     if(asciiSend)
  529.     if (OKToSendChar(paceCh,doPacing,sOut,&foundPaceChar))
  530.       {
  531.           cnt = 1;
  532.           err = FSRead(sendRef,&cnt,&ch);
  533.           if(!err) {
  534.                      ProcessChar(ch,0,sOut,0);  /* dummy code */
  535.                      Delay(delayAmt,&tmp); 
  536.                      if(ch == CR) foundPaceChar = false;
  537.                     }
  538.           else {if (err != eofErr)
  539.                         ErrorMessage("Error During File Read",err);
  540.                 FSClose(sendRef); sendRef = 0;
  541.                 SetItem(FileMenu,2,"Start Text Upload...");
  542.                 asciiSend = false; }
  543.         }
  544.      
  545.      
  546.     if (GetNextEvent(everyEvent,&event))
  547.     switch (event.what) {
  548.         case mouseDown:
  549.         switch (FindWindow(&event.where,&whichwindow)) {
  550.           case inMenuBar:
  551.             if (sel = MenuSelect(&event.where))
  552.                 DoMenu(sel);
  553.             break;
  554.           case inSysWindow:
  555.             SystemClick(&event,whichwindow);
  556.             break;
  557.           case inDrag:
  558.             DragWindow(whichwindow,&event.where,&dragRect);
  559.             break;
  560.           case inGoAway:
  561.             if (TrackGoAway(whichwindow,&event.where))
  562.               /* action  exit(); */
  563.             break;
  564.           case inGrow:
  565.           case inContent:
  566.             if (whichwindow != FrontWindow())
  567.                 SelectWindow(whichwindow);
  568.             break;
  569.         }
  570.         break;
  571.         case keyDown:
  572.         case autoKey:
  573.         if (myWindow == FrontWindow()) {
  574.             ch = (char)event.message;
  575.             code = (event.message & keyCodeMask) >> 8;
  576.             if (event.modifiers & cmdKey) {
  577.                    if(!HiWord(MenuKey(ch))) /* not a system item */
  578.                          ch = ch & 0x1F ;    /* convert to control key */
  579.             }
  580.              ProcessChar(ch,code,sOut,event.modifiers) ;    /* write char to modem */
  581.         }
  582.           break;
  583.         case app2Evt: if (showClock) showTime();
  584.                       break;
  585.         case activateEvt:
  586.           /* in this simple shell we will turn off/on the edit menu */
  587.           whichwindow = (WindowPtr) event.message;
  588.           if(whichwindow == myWindow){      /* It's our window */
  589.           if(event.modifiers & activeFlag) /* and it's going active */
  590.            {
  591.               SetPort(whichwindow);   /* make SURE drawing works */
  592.               DisableItem(EditMenu,0);/* disable entire menu */
  593.               DrawMenuBar();          /* and redraw the menu bar */
  594.               start_cursor();          /* crank up the cursor */
  595.             }
  596.           else  /* our window has been deactivated */
  597.            { EnableItem(EditMenu,0);  /* Turn on standard edit items */
  598.              DrawMenuBar();
  599.              stop_cursor();              /* stop the cursor */
  600.             }
  601.           }
  602.  
  603.           break;
  604.         case updateEvt:
  605.           whichwindow = (WindowPtr) event.message;
  606.           if (whichwindow == myWindow){ /* it's our window */
  607.           GetPort(&tmpWindow);SetPort(whichwindow); /* set port */
  608.             BeginUpdate(whichwindow);
  609.               DoUpDate();
  610.             EndUpdate(whichwindow);
  611.           SetPort(tmpWindow); /* restore previous port */
  612.           }
  613.           break;
  614.       }
  615. }
  616. main(){
  617.  
  618.  UnloadSeg(_DataInit);        /* unload the runtime initializer code */
  619.  
  620.  if(!InitProgram()) return;    /*  Initialization fails -> quit */
  621.  
  622.  UnloadSeg(InitProgram);    /* Unload initialization code */
  623.  
  624.  while(moreToDo){
  625.    docursor();                /* flash cursor */
  626.    ReadPort(sIn);            /* echo any characters from remote system */
  627.    MainEventLoop();
  628.   }
  629.  }